using System;
using System.Globalization;
using GammaJul.ReSharper.GammaXaml.Highlightings.CSharp;
using GammaJul.ReSharper.GammaXaml.Psi.Xaml;
using JetBrains.Annotations;
using JetBrains.Application.Progress;
using JetBrains.ProjectModel;
using JetBrains.ReSharper.Feature.Services.Bulbs;
using JetBrains.ReSharper.Intentions.Extensibility;
using JetBrains.ReSharper.Intentions.Util;
using JetBrains.ReSharper.Psi;
using JetBrains.ReSharper.Psi.CSharp;
using JetBrains.ReSharper.Psi.CSharp.Tree;
using JetBrains.ReSharper.Psi.Util;
using JetBrains.ReSharper.Psi.Xaml.Impl.Resolve;
using JetBrains.TextControl;
using JetBrains.Util;

namespace GammaJul.ReSharper.GammaXaml.QuickFixes.CSharp {

	/// <summary>
	/// Quick fix that changes a dependency property registered type.
	/// </summary>
	[QuickFix]
	public sealed class ChangeDpTypeFix : QuickFixBase {
		private readonly MismatchedDpAccessorTypeHighlighting _highlighting;
		
		public override string Text {
			get {
				IType type = _highlighting.Accessor.Type();
				Assertion.Assert(type != null, "type != null");
				return String.Format(
					CultureInfo.CurrentCulture,
					"Change registered type of '{0}' to '{1}'",
					_highlighting.DpField.ShortName,
					type.GetPresentableName(CSharpLanguage.Instance));
			}
		}
		
		protected override Action<ITextControl> ExecutePsiTransaction(ISolution solution, IProgressIndicator progress) {
			foreach (IFieldDeclaration declaration in _highlighting.DpField.GetDeclarations()) {
				DpInitInfo dpInitInfo = declaration.GetDpOrDpKeyInitInfo(XamlTypeCache.GetCache(declaration));
				ITypeofExpression typeofExpr = dpInitInfo.PropertyTypeofExpression;
				if (typeofExpr != null) {
					var elementFactory = CSharpElementFactory.GetInstance(typeofExpr.GetPsiModule());
					typeofExpr.SetTypeName(elementFactory.CreateTypeUsageNode(_highlighting.Accessor.Type()));
				}
			}
			
			return null;
		}

		public override bool IsAvailable(IUserDataHolder cache) {
			return _highlighting.IsValid()
				&& ValidUtils.Valid(_highlighting.DpField, true);
		}

		public ChangeDpTypeFix([NotNull] MismatchedDpAccessorTypeHighlighting highlighting) {
			if (highlighting == null)
				throw new ArgumentNullException("highlighting");
			_highlighting = highlighting;
		}
	}

}
